<p><code>
内容：Node基础
日期：xx-xx-xx
</code></p>

<h1>一、npm与包</h1>

<h2>1. 包的概念：</h2>

<p>​		Node.js 中的第三方模块又叫做包。就像电脑和计算机指的是同一个事物，第三方模块和包指的是同一个概念，只不过叫法不同</p>

<p>主要内容有：</p>

<p>​		(1)包管理工具 （npm）（用来下载第三方模块）</p>

<p>​		(2)npm 社区  </p>

<h3>包来源</h3>

<p>包是由第三方个人或团队开发出来的，免费供给所有开发者使用。 npm 社区 https://www.npmjs.com/</p>

<h3>包的特点</h3>

<ul><li><p>在 Node.js 中，如果只用内置模块或开发者自己定义模块开发，效率会很低。所以就有 了第 3 方模块（包）</p></li><li><p>包是基于内置模块封装出来的，提供了更高级、更方便的 API，极大的提高了开发效率 </p></li><li><p>包（第三方模块）和模块之间的关系，类似于 Jquery 和 原生 js 之间的关系 </p></li><li><p>要想称为一个包除了遵守模块化规范以外，还要遵守包的一些规范，如：说明文档，协议说明等</p></li></ul>

<h2>2. 包管理工具 npm</h2>

<p>包管理工具指的是安装node环境后，自动安装了npm工具。Node Package Manager，简称 npm 包管理工具。</p>

<h3>2.1 版本号的介绍</h3>

<p>一般来讲大部分的软件版本号分 3 段，Node.js 中的包也遵循这样的规则，比如：4.17.1。 </p>

<p>每位数字的含义： </p>

<ul><li>第 1 位数字：表示大版本号，一般当软件整体重写，或出现不向后兼容的改变时，增加此位， 此位是 0 时表示软件还在开发阶段。 </li><li>第 2 位数字：表示功能更新，出现新功能时增加此位 </li><li>第 3 位数字：表示小修改，如修复 bug，只要有修改就增加此位 </li></ul>

<h3>2.2 第一次安装包的说明</h3>

<ul><li>初次装包完成后，在项目文件夹下多一个 node_modules 的文件夹和 package-lock.json的配置文件 </li><li>node_modules 文件夹用来存放所有已安装到项目中的第三方包。require() 导入第三方包时，就是从这个目录中查找并加载包 </li><li>package-lock.json 配置文件用来记录node_modules 目录下的每一个包的下载信息， 例如包的名字、版本号、下载地址等 </li><li>开发者不要手动修改 node_modules 或 package-lock.json 文件中的任何代码，npm 包管理工具会自动维护它们 </li></ul>

<h2>3. 常用命令</h2>

<h3>3.1 npm  init  [ -y ]</h3>

<p>作用：</p>

<p>一问一答初始化项目并创建 package.json。</p>

<p>-y （可选参数） 代表直接生成 package.json,所有的项都保持默认。</p>

<p>当前项目文件夹名不要有中文、特殊符号、空格。</p>

<p>不要使用第三方模块名称和内置模块的名称定义项目文件夹名（不要占用关键字）</p>

<p>初始化：可以手动的在项目的根目录下创建package.json文件，在文件中写入一些配置：</p>

<p>但是一般使用命令去创建</p>

<p><code>json
// 本文件中不能出现注释
{
    &quot;name&quot;: &quot;demo&quot;,// 项目的名称（默认是项目根文件夹的名称，不能是中文和特殊字符）
    &quot;main&quot;: &quot;&quot;, //入口文件，别人访问你这项目或模块时的入口（直接访问到文件夹的时候自动进入这个文件,此文件默认是index.js）
    &quot;dependencies&quot;: {},//生产依赖,项目的依赖项（依赖其他模块）
    &quot;devDependencies&quot;: {},//开发依赖
    // 协议
    // 本项目的版本号
    // 。。。。。。
}
</code></p>

<h3>3.2 安装某包</h3>

<h4>2.1 npm   install   包名</h4>

<p>作用：安装最新版本的包，安装某版本的包</p>

<p>说明：install 安装，i是install的简写</p>

<p><code></code>`sh
npm   install   包名  #下载一个包
npm   install   包名1  包名2 。。。 #下载多个包</p>

<p>npm   install   包名1@版本号  包名2@版本号 。。。
<code></code>`</p>

<h4>3.2.2 npm   install   包名   [-S|--save]</h4>

<p>作用：安装最新版本的包，并且保存到 dependencies 属性中</p>

<p>说明：--sava 将下载的包的记录保存到 dependencies 属性中，-S 是--save 的简写</p>

<p>（npm 之前是必须要添加--sava的参数的，现在不需要了，可以不写了）</p>

<p>（cnpm 仍然需要使用 --save）</p>

<h4>3.2.3 npm  install   包名   [ -D|--save-dev]</h4>

<p>作用：安装最新版本的包，并且保存到 devDependencies 属性中 </p>

<p>说明：--save-dev 将下载的包的记录保存到 devDependencies 属性中， -D 是--save-dev 的简写</p>

<h4>3.2.4  npm    install   包名   -g</h4>

<p>作用：安装全局包</p>

<p>全局包安装位置：C:\Users\用户名\AppData\Roaming\npm</p>

<h3>3.3  npm  uninstall/un   包名   [ -g ]</h3>

<p>作用：卸载包</p>

<h2>4.npm包手册</h2>

<p>每个包的使用方式</p>

<p>以trim为例</p>

<p>https://www.npmjs.com/package/trim</p>

<p><img alt="第三方模块手册" src="img/第三方模块手册.png"/></p>

<h2>5. npm 淘宝镜像</h2>

<p>Node.js 中的 npm 淘宝镜像指：淘宝在国内免费为开发者提供了一个服务器，专门把国外官方服务器上的包同步到国内的服务器，供国内开发者使用</p>

<p>淘宝镜像官方：https://developer.aliyun.com/mirror/NPM</p>

<p><img alt="2-10淘宝镜像" src="img/2-10淘宝镜像.png"/></p>

<p>npm 官方下载地址：https://registry.npmjs.org   国外的服务器太慢了</p>

<p>使用淘宝镜像：</p>

<p>第一种方式：全局安装cnpm工具，并而配置cnmp下载模块的地址（ 然后，我们npm工具如何使用的，cnpm一模一样 ）</p>

<p><code>
npm install -g cnpm --registry=https://registry.npmmirror.com
</code></p>

<p>第二种方式：配置npm命令的源：</p>

<p><code>sh
npm config set registry https://registry.npmmirror.com 
</code></p>

<p>检查是否设置成功：</p>

<p><code>sh
npm config get registry
</code></p>

<h2>6.package.json</h2>

<p>​		按照规范：在项目根目录中，必须提供一个叫做 package.json 的包管理配置文件。可以简称为项目管家 ，记录你的项目和npm下载的各个包的信息。</p>

<h3>6.1 开发中的问题</h3>

<p>第三方包占用空间过大，不方便团队成员之间共享项目源代码</p>

<p><img alt="团队开发的问题" src="img\团队开发的问题.png"/></p>

<h3>6.2 使用步骤</h3>

<ol><li>创建一个package.json文件</li></ol>

<p>注意：此文件不能为空，且必须是json字符串</p>

<p>​	2. 在项目当中下载你需要的包，比如：trim和time-stamp</p>

<p>​		npm工具下载包完成以后，会记录在package.json中的dependencies中（之前的npm和cnpm需要：--save）</p>

<ol><li><p>共享项目源代码时，把node_modules删掉，但是千万别删 package.json文件。</p></li><li><p>接收到共享项目源代码时，在项目根目录下打开cmd，运行npm  i  重新下载所有dependencies中记录的包</p></li></ol>

<p>​       团队开发中使用git分享代码，应该先使用.gitignore把 node_modues给忽略掉</p>

<h3>6.3 package.json中的属性</h3>

<p>完整属性如下表:</p>

<p>| 属性名              | 说明                                                         |
| ------------------- | ------------------------------------------------------------ |
| <strong>name</strong>            | 包（项目）的名称（不能有中文和特殊字符和第三方和内置模块的没名字） |
| version             | 包（项目）的版本号                                           |
| description         | 包（项目）的描述                                             |
| <strong>main</strong>            | 包（项目）入口文件  （默认是index.js）                       |
| <strong>scripts</strong>         | 定义快捷脚本命令                                             |
| keywords            | 项目关键词                                                   |
| author              | 作者                                                         |
| license             | 协议                                                         |
| <strong>dependencies</strong>    | 包（项目）生产依赖的模块                                     |
| <strong>devDependencies</strong> | 包（项目）开发依赖的模块   develop                           |</p>

<h4>dependencies</h4>

<p><code>sh
npm i 包名   #会自动的记录到dependencies属性中 相当于npm i 包名 -S 或 npm i 包名 --save
</code></p>

<h4>devDependencies</h4>

<p><code>sh
npm install/i 包名  -D/--save-dev     #会自动的记录到devDependencies属性中
</code></p>

<h3>6.4 使用npm init 自动创建package.json</h3>

<p>package.json应该包含 name，version，main</p>

<p>文件夹名不要有中文</p>

<p>不要使用第三方模块名称和内置模块的名称定义项目文件夹名</p>

<h2>7. 包的分类</h2>

<h3>7.1 项目包</h3>

<p>被安装到项目的node_modules 目录中的包，都是项目包。项目包又分为两类： </p>

<ul><li><p>#### 开发依赖包：</p><p>被记录到 devDependencies 节点中的包，只在开发期间会用到 </p></li><li><p>#### 核心（生产）依赖包：</p><p>被记录到 dependencies 节点中的包，在开发期间和项目上线之后都用到。当然一个项目中会用到很多包，短期内记忆较为困难，简单的方法就是都安装在 dependencies 中。 </p><p>总结：我们的包会很多很多，但是只记录自己下载的包即可（package.json帮我们记录）</p></li></ul>

<h3>7.2 全局包</h3>

<p>工具类的包称为全局包，和npm这个工具一样，并不是在代码文件中引入的，是在 cmd 命令行使用的。 </p>

<p>常用的有 ： webpack   nodemon    npm    node </p>

<h4>7.2.1 安装命令：</h4>

<p><code>sh
npm i 包名 -g   # -g : global
</code></p>

<h4>7.2.2 使用特点：</h4>

<ul><li>并不是在代码文件中引入的，全局包像 npm 一样在终端中使用的 </li><li>决定某个包是否需要全局安装，需要参考官方提供的使用说明书 </li><li>全局包会被安装到 C:\Users\用户目录\AppData\Roaming\npm\node_modules 目录下</li></ul>

<h4>7.2.3 以markdown工具包为例：</h4>

<h5>安装：工具包在一个电脑上只需安装一次就行</h5>

<p><code>sh
npm install -g markdown
</code></p>

<h5>把 .md 文件 转换成 html文件</h5>

<p><code>sh
md2html xxx.md &gt; yyy.html
</code></p>

<h2>8. 包加载机制</h2>

<h3>8.1 内置模块的加载机制</h3>

<ul><li>内置模块是由 Node.js 官方提供的模块，内置模块的加载优先级最高。</li><li>例如， require(&#39;fs&#39;) 始终返回内置的 fs 模块，即使在 node_modules 目录下有名字相同的包也 叫做 fs，也会引入核心的内置fs模块。</li><li>所以第三方模块和自定义模块不要起官网已有的模块名称 </li></ul>

<h3>8.2 自定义模块加载机制</h3>

<ul><li>使用 require() 加载自定义模块时，必须指定以 ./ 或 ../ 开头的路径标识符。 </li><li>如果没有指定 ./ 或 ../ 这样的路径标识符，则 Node.js 会把它当作内置模块或 第三方模块进行加载。 </li><li>自定义模块不要写在node_modules中</li><li><p>在require()引入自定义模块时，可以省略扩展名。如果省略了文件的扩展名，则Node.js会按顺序分别尝试加载以下文件：</p><ul><li>文件名.js </li><li>文件名.json   </li><li><p>加载失败，终端报错 Error: Cannot  module  &#39;xxx&#39; </p></li></ul></li><li><p>模块可以省略文件名，只引入到文件夹名（ 默认找index.js ）</p></li></ul>

<h3>8.3 第三方模块加载机制</h3>

<ul><li><p>第三方模块一定是下载到项目根目录下的 node<em>modules ，且项目中只有根目录下有 node</em>modules</p></li><li><p>如果 require() 的模块标识符不是内置模块，也没有以 ‘./’ 或 ‘../’ 开头， 则 Node.js 会从当前模块的父目录开始，尝试从当前文件夹的/node_modules 文件夹 中加载第三方模块。 </p></li><li><p>如果没有找到对应的第三方模块，则移动到再上一层父目录中，进行加载，直到当前项目文件的盘符根目录</p></li></ul>

<h3>8.4 package.json 中的 main 属性</h3>

<p>main 属性，可以指定模块加载的主入口文件，当引入模块时用文件夹名结尾时生效。 </p>

<h4>有三种加载方式：</h4>

<ul><li><p>根据目录下的 package.json 的文件，寻找 main 属性指定的文件名，作为 require()加载的入口。 </p></li><li><p>如果目录里没有 package.json 文件，或者 main 入口不存在或无法解析，则Node.js 将会加载目录下的 index.js文件（所以默认目录中的默认入口为 index.js）。 </p></li><li><p>如果以上两步都加载失败，则 Node.js 会在终端打印错误消息，报告模块缺失： Error: Cannot </p></li></ul>
